﻿namespace AC.ExtendedRenderer.RibbonStyle
{
    using System;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Windows.Forms;

    [ToolboxBitmap(typeof(Button))]
    public class RibbonRoundButton : Button
    {
        private Color _baseColor = Color.FromArgb(0xd1, 0xd1, 0xd1);
        private Color _hoverColor = Color.FromArgb(0xff, 0xff, 0xff);
        private Point _imgoffset = new Point(0, 0);
        private int _imgscale = 100;
        private Color _onColor = Color.FromArgb(0xff, 0xff, 0xff);
        private Color _onColorlight = Color.FromArgb(0xff, 0xff, 0xff);
        private Color _pressColor = Color.FromArgb(0xff, 0xff, 0xff);
        private Color _strokeColor = Color.FromArgb(80, 80, 80);
        private int B0;
        private int G0;
        private int i_factor = 20;
        private int i_fB = 1;
        private int i_fG = 1;
        private int i_fR = 1;
        private int i_mode;
        private int R0;
        private int regionoffset = 1;
        private Timer timer1 = new Timer();

        public RibbonRoundButton()
        {
            base.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.SupportsTransparentBackColor | ControlStyles.ResizeRedraw | ControlStyles.UserPaint, true);
            base.SetStyle(ControlStyles.Opaque, false);
            base.FlatAppearance.BorderSize = 0;
            base.FlatStyle = FlatStyle.Flat;
            this.BackColor = Color.Transparent;
            base.TextImageRelation = TextImageRelation.ImageAboveText;
            this.Text = "";
            base.Size = new Size(40, 40);
            this.timer1.Interval = 1;
            this.timer1.Tick += new EventHandler(this.timer1_Tick);
        }

        public void DrawImage(Graphics gr, Rectangle re, Point off, int scale)
        {
            if (base.Image != null)
            {
                gr.DrawImage(base.Image, off.X, off.Y, (int) ((re.Width * scale) / 100), (int) ((re.Height * scale) / 100));
            }
        }

        public void DrawStroke(Graphics gr, Rectangle re, int stroke, Color incolor, Color outcolor)
        {
            Rectangle rect = new Rectangle(stroke, stroke, (base.Width - (3 * stroke)) - this.regionoffset, (base.Height - (3 * stroke)) - this.regionoffset);
            gr.DrawEllipse(new Pen(incolor, (float) stroke), rect);
        }

        public void FillBeizer(Graphics gr, Rectangle re, int stroke, Color incolor, Color basecolor)
        {
            new Rectangle(stroke, stroke, (re.Width - (2 * stroke)) - this.regionoffset, (re.Height - (2 * stroke)) - this.regionoffset);
            GraphicsPath path = new GraphicsPath();
            Point[] points = new Point[] { new Point(re.Width / 2, 1), new Point(2, re.Height / 2), new Point(re.Width / 2, (int) ((re.Height / 2) * 0.9)), new Point(re.Width - 2, re.Height / 2) };
            path.AddClosedCurve(points, 1.16f);
            PathGradientBrush brush = new PathGradientBrush(path);
            brush.CenterPoint = new PointF((float) (base.Width / 2), (float) base.Height);
            float[] numArray = new float[] { 0f, 0.018f, 0.15f, 1f };
            Color[] colorArray = new Color[] { Color.FromArgb(10, incolor), Color.FromArgb(200, incolor), Color.FromArgb(30, incolor), Color.FromArgb(10, incolor) };
            ColorBlend blend = new ColorBlend();
            blend.Colors = colorArray;
            blend.Positions = numArray;
            brush.InterpolationColors = blend;
            gr.CompositingQuality = CompositingQuality.HighQuality;
            gr.FillPath(brush, path);
            brush.Dispose();
        }

        public void FillGradient(Graphics gr, Rectangle re, Color incolor, Color outcolor)
        {
            try
            {
                Rectangle rect = new Rectangle((int) (re.Width * -0.15), (int) (re.Height * 0.12), ((int) (re.Width * 1.26)) - this.regionoffset, ((int) (re.Height * 0.875)) - this.regionoffset);
                GraphicsPath path = new GraphicsPath();
                path.AddEllipse(rect);
                PathGradientBrush brush = new PathGradientBrush(path);
                brush.CenterPoint = new PointF((float) (base.Width / 2), (float) base.Height);
                float[] numArray = new float[] { 0f, 0.2f, 0.3f, 0.7f, 1f };
                Color[] colorArray = new Color[] { Color.FromArgb(10, incolor), Color.FromArgb(10, incolor), Color.FromArgb(40, outcolor), incolor, incolor };
                ColorBlend blend = new ColorBlend();
                blend.Colors = colorArray;
                blend.Positions = numArray;
                brush.InterpolationColors = blend;
                gr.FillPath(brush, path);
                brush.Dispose();
            }
            catch
            {
            }
        }

        public void FillShadow(Graphics gr, Rectangle re)
        {
            int x = 1;
            Color black = Color.Black;
            new Rectangle(x, x, re.Width - (2 * x), re.Height - (2 * x));
            GraphicsPath path = new GraphicsPath();
            path.AddArc(1, 1, base.Width - 2, base.Height - 2, 270f, 210f);
            PathGradientBrush brush = new PathGradientBrush(path);
            brush.CenterPoint = new PointF((float) (base.Width / 2), (float) (base.Height / 2));
            float[] numArray = new float[] { 0f, 0.01f, 0.5f, 1f };
            Color[] colorArray = new Color[] { Color.FromArgb(0, black), Color.FromArgb(100, black), Color.FromArgb(0, black), Color.FromArgb(0, black) };
            ColorBlend blend = new ColorBlend();
            blend.Colors = colorArray;
            blend.Positions = numArray;
            brush.InterpolationColors = blend;
            gr.CompositingQuality = CompositingQuality.HighQuality;
            gr.FillPath(brush, path);
            brush.Dispose();
        }

        public void FillStroke(Graphics gr, Rectangle re, int stroke, Color incolor)
        {
            Rectangle rect = new Rectangle(stroke, stroke, (base.Width - (2 * stroke)) - this.regionoffset, (base.Height - (2 * stroke)) - this.regionoffset);
            gr.FillEllipse(new SolidBrush(incolor), rect);
        }

        public Color GetLightColor()
        {
            int red = this.R0 + 0x7f;
            int green = this.G0 + 0xc4;
            int blue = this.B0 + 0x6f;
            if (red > 0xff)
            {
                red = 0xff;
            }
            if (green > 0xff)
            {
                green = 0xff;
            }
            if (blue > 0xff)
            {
                blue = 0xff;
            }
            return Color.FromArgb(red, green, blue);
        }

        protected override void OnMouseDown(MouseEventArgs mevent)
        {
            this.timer1.Stop();
            this.i_mode = 2;
            this.timer1.Start();
            base.OnMouseDown(mevent);
        }

        protected override void OnMouseEnter(EventArgs e)
        {
            this.i_mode = 0;
            this.timer1.Start();
            base.OnMouseEnter(e);
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            this.i_mode = 1;
            this.timer1.Start();
            base.OnMouseLeave(e);
        }

        protected override void OnMouseUp(MouseEventArgs mevent)
        {
            this.timer1.Stop();
            this.i_mode = 3;
            this.timer1.Start();
            base.OnMouseUp(mevent);
        }

        protected override void OnPaint(PaintEventArgs pevent)
        {
            Graphics gr = pevent.Graphics;
            gr.SmoothingMode = SmoothingMode.HighQuality;
            gr.InterpolationMode = InterpolationMode.High;
            Rectangle re = new Rectangle(0, 0, base.Width - this.regionoffset, base.Height - this.regionoffset);
            GraphicsPath path = new GraphicsPath();
            Size size = base.Size;
            path.AddEllipse(0, 0, base.Width - 1, base.Height - 1);
            base.Region = new Region(path);
            this.FillShadow(gr, re);
            this.FillStroke(gr, re, 2, Color.FromArgb(this.R0, this.G0, this.B0));
            this.FillGradient(gr, re, this.GetLightColor(), Color.FromArgb(this.R0, this.G0, this.B0));
            this.FillBeizer(gr, re, 1, this.ColorOver, this.ColorBase);
            this.DrawImage(gr, re, this.ImgOffset, this.ImgScale);
            this.DrawStroke(gr, re, 1, this.ColorStroke, this.GetLightColor());
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if ((this.i_mode == 0) | (this.i_mode == 3))
            {
                if (Math.Abs((int) (this.ColorOn.R - this.R0)) > this.i_factor)
                {
                    this.i_fR = this.i_factor;
                }
                else
                {
                    this.i_fR = 1;
                }
                if (Math.Abs((int) (this.ColorOn.G - this.G0)) > this.i_factor)
                {
                    this.i_fG = this.i_factor;
                }
                else
                {
                    this.i_fG = 1;
                }
                if (Math.Abs((int) (this.ColorOn.B - this.B0)) > this.i_factor)
                {
                    this.i_fB = this.i_factor;
                }
                else
                {
                    this.i_fB = 1;
                }
                if (this.ColorOn.R < this.R0)
                {
                    this.R0 -= this.i_fR;
                }
                else if (this.ColorOn.R > this.R0)
                {
                    this.R0 += this.i_fR;
                }
                if (this.ColorOn.G < this.G0)
                {
                    this.G0 -= this.i_fG;
                }
                else if (this.ColorOn.G > this.G0)
                {
                    this.G0 += this.i_fG;
                }
                if (this.ColorOn.B < this.B0)
                {
                    this.B0 -= this.i_fB;
                }
                else if (this.ColorOn.B > this.B0)
                {
                    this.B0 += this.i_fB;
                }
                if (this.ColorOn == Color.FromArgb(this.R0, this.G0, this.B0))
                {
                    this.timer1.Stop();
                }
                else
                {
                    this.Refresh();
                }
            }
            if (this.i_mode == 2)
            {
                if (Math.Abs((int) (this.ColorPress.R - this.R0)) > this.i_factor)
                {
                    this.i_fR = this.i_factor;
                }
                else
                {
                    this.i_fR = 1;
                }
                if (Math.Abs((int) (this.ColorPress.G - this.G0)) > this.i_factor)
                {
                    this.i_fG = this.i_factor;
                }
                else
                {
                    this.i_fG = 1;
                }
                if (Math.Abs((int) (this.ColorPress.B - this.B0)) > this.i_factor)
                {
                    this.i_fB = this.i_factor;
                }
                else
                {
                    this.i_fB = 1;
                }
                if (this.ColorPress.R < this.R0)
                {
                    this.R0 -= this.i_fR;
                }
                else if (this.ColorPress.R > this.R0)
                {
                    this.R0 += this.i_fR;
                }
                if (this.ColorPress.G < this.G0)
                {
                    this.G0 -= this.i_fG;
                }
                else if (this.ColorPress.G > this.G0)
                {
                    this.G0 += this.i_fG;
                }
                if (this.ColorPress.B < this.B0)
                {
                    this.B0 -= this.i_fB;
                }
                else if (this.ColorPress.B > this.B0)
                {
                    this.B0 += this.i_fB;
                }
                if (this.ColorPress == Color.FromArgb(this.R0, this.G0, this.B0))
                {
                    this.timer1.Stop();
                }
                else
                {
                    this.Refresh();
                }
            }
            if (this.i_mode == 1)
            {
                if (Math.Abs((int) (this.ColorBase.R - this.R0)) < this.i_factor)
                {
                    this.i_fR = 1;
                }
                else
                {
                    this.i_fR = this.i_factor;
                }
                if (Math.Abs((int) (this.ColorBase.G - this.G0)) < this.i_factor)
                {
                    this.i_fG = 1;
                }
                else
                {
                    this.i_fG = this.i_factor;
                }
                if (Math.Abs((int) (this.ColorBase.B - this.B0)) < this.i_factor)
                {
                    this.i_fB = 1;
                }
                else
                {
                    this.i_fB = this.i_factor;
                }
                if (this.ColorBase.R < this.R0)
                {
                    this.R0 -= this.i_fR;
                }
                else if (this.ColorBase.R > this.R0)
                {
                    this.R0 += this.i_fR;
                }
                if (this.ColorBase.G < this.G0)
                {
                    this.G0 -= this.i_fG;
                }
                else if (this.ColorBase.G > this.G0)
                {
                    this.G0 += this.i_fG;
                }
                if (this.ColorBase.B < this.B0)
                {
                    this.B0 -= this.i_fB;
                }
                else if (this.ColorBase.B > this.B0)
                {
                    this.B0 += this.i_fB;
                }
                if (this.ColorBase == Color.FromArgb(this.R0, this.G0, this.B0))
                {
                    this.timer1.Stop();
                }
                else
                {
                    this.Refresh();
                }
            }
        }

        public Color ColorBase
        {
            get
            {
                return this._baseColor;
            }
            set
            {
                this._baseColor = value;
                this.R0 = this._baseColor.R;
                this.B0 = this._baseColor.B;
                this.G0 = this._baseColor.G;
            }
        }

        public Color ColorOn
        {
            get
            {
                return this._onColor;
            }
            set
            {
                this._onColor = value;
            }
        }

        public Color ColorOver
        {
            get
            {
                return this._hoverColor;
            }
            set
            {
                this._hoverColor = value;
            }
        }

        public Color ColorPress
        {
            get
            {
                return this._pressColor;
            }
            set
            {
                this._pressColor = value;
            }
        }

        public Color ColorStroke
        {
            get
            {
                return this._strokeColor;
            }
            set
            {
                this._strokeColor = value;
            }
        }

        public Point ImgOffset
        {
            get
            {
                return this._imgoffset;
            }
            set
            {
                this._imgoffset = value;
                this.Refresh();
            }
        }

        public int ImgScale
        {
            get
            {
                return this._imgscale;
            }
            set
            {
                this._imgscale = value;
                this.Refresh();
            }
        }
    }
}

